

const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g; // 判断{{}}的正则

// 拼接属性字符串
function formatProps(attrs){
    let attrsStr = '';
    for (var i =0; i < attrs.length; i++){
        let attr = attrs[i];
        // 对style属性进行特殊处理
        if (attr.name === 'style'){
            // 拿到style的值
            let styleAttrs = {}
            attr.value.split(';').map((style)=>{
                // 拿到样式的key和value
                let [key,value]= style.split(':');
                styleAttrs[key] = value
            })
            attr.value = styleAttrs;
        }
        attrsStr += `${attr.name}:${JSON.stringify(attr.value)},`
    }
    
    return `{${attrsStr.slice(0,-1)}}` // 去掉最后一个逗号
}

function generateChild(node){   
    // 如果是元素节点直接生成代码
    if (node.type == 1){
        return generate(node)
    }else if (node.type === 3){
        // 文本节点
        let text = node.text;
        // 不是{{}}包裹的文本节点直接转义输出
        if (!defaultTagRE.test(text)){
            return `_v(${JSON.stringify(text)})` // 不是{{}}包裹的文本节点,直接转义输出
        }

        let match;
        let index;
        let lastIndex = defaultTagRE.lastIndex = 0; // 匹配的开始位置
        let textArr = [];
        // 匹配{{}}包裹的文本
        while(match = defaultTagRE.exec(text)){
            index = match.index;
            // index 就是{{}} 的开始位置字符串索引值
            // lastIndex 是上一次{{}}的结束位置字符串索引值
            // index的索引值大于了上一次匹配到{{}}的索引值，说明中间有普通字符串，类似这样(你好，{{ name }} 欢迎来到小野森森的课堂 )
            if (index > lastIndex){
                // 先将中间的普通字符串转义输出
                textArr.push(JSON.stringify(text.slice(lastIndex,index)))
            }
            // 匹配{{}}包裹的文本转义输出 将{{}} 转成函数 _s
            textArr.push(`_s(${match[1].trim()})`);
            // 更新上一次匹配到的{{}}的结束位置
            lastIndex = index + match[0].length;
            
        }
        // 如果{{}}匹配的文本最后还有剩余的字符串，转义输出
        if (lastIndex < text.length){
            textArr.push(JSON.stringify(text.slice(lastIndex)));
        }

        // 拼接字符串
        return `_v(${textArr.join('+')})`;
    }
}

function getChildren(el){
    const children = el.children;
    if (children) {
      return children.map(c => generateChild(c)).join(',');
    }
}

// 将AST生成代码
function generate(el){
    let children = getChildren(el);
    
    let code = `_c('${ el.tag }', ${
        el.attrs.length > 0 
        ?
        `${ formatProps(el.attrs) }`
        :
        'undefined'
      }${
        children ? `,${children}` : ''
      })`;
    
    return code;
    
    
    
}

export{
    generate
}